package com.wxg.netty.webchat;

import io.netty.channel.*;
import io.netty.handler.codec.http.*;
import io.netty.handler.ssl.SslHandler;
import io.netty.handler.stream.ChunkedNioFile;

import java.io.File;
import java.io.RandomAccessFile;
import java.net.URISyntaxException;
import java.net.URL;

public class HttpRequestHandler extends SimpleChannelInboundHandler<FullHttpRequest> { // (1)
    private final String wsUri;
    private static final File INDEX;

    public HttpRequestHandler(String wsUri) {
        this.wsUri = wsUri;
    }

    static {
        URL location = HttpRequestHandler.class.getProtectionDomain().getCodeSource().getLocation();
        try {
            String path = location.toURI() + "WebSocketChatClient.html"; // WebSocketChatClient, hello
            path = !path.contains("file:") ? path : path.substring(5);
            System.out.println(path);
            INDEX = new File(path);
        } catch (URISyntaxException e) {
            throw new IllegalStateException("Unable to locate WebSocketChatClient.html");
        }
    }

    @Override
    protected void channelRead0(ChannelHandlerContext ctx, FullHttpRequest request) throws Exception {

        System.out.println("wsUri : " + wsUri);
        System.out.println("request.uri() : " + request.uri());

        if(wsUri.equalsIgnoreCase(request.uri())){
            ctx.fireChannelRead(request.retain());  // (2)
        }else{

            System.out.println("is100ContinueExpected : " + HttpUtil.is100ContinueExpected(request));

            if(HttpUtil.is100ContinueExpected(request)){
                send100Continue(ctx);  // (3)
            }

            RandomAccessFile file = new RandomAccessFile(INDEX, "r");  // (4)

            HttpResponse response = new DefaultFullHttpResponse(request.protocolVersion(), HttpResponseStatus.OK);
            response.headers().set(HttpHeaderNames.CONTENT_TYPE, "text/html; charset=UTF-8");
            boolean keepAlive = HttpUtil.isKeepAlive(request);

            System.out.println("keepAlive : " + keepAlive);

            if (keepAlive){  // (5)
                response.headers().set(HttpHeaderNames.CONTENT_LENGTH, file.length());
                // HttpHeaderNames.KEEP_ALIVE -> HttpHeaderNames.CONNECTION
                // response.headers().set(HttpHeaderNames.CONNECTION, HttpHeaderNames.CONNECTION);
                response.headers().set(HttpHeaderNames.CONNECTION, HttpHeaders.Values.KEEP_ALIVE);
            }
            ctx.write(response);  // (6)

            if (ctx.pipeline().get(SslHandler.class) == null){  // (7)
                ctx.write(new DefaultFileRegion(file.getChannel(), 0, file.length()));
            } else {
                ctx.write(new ChunkedNioFile(file.getChannel()));
            }

            ChannelFuture future = ctx.writeAndFlush(LastHttpContent.EMPTY_LAST_CONTENT); // (8)

            if(!keepAlive){
                future.addListener(ChannelFutureListener.CLOSE);  // (9)
            }

            System.out.println("file.close()");

            file.close();
        }
    }

    private static void send100Continue(ChannelHandlerContext ctx) {
        FullHttpResponse response = new DefaultFullHttpResponse(HttpVersion.HTTP_1_1, HttpResponseStatus.CONTINUE);
        ctx.writeAndFlush(response);
    }

    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
        Channel incoming = ctx.channel();
        System.out.println("Client: " + incoming.remoteAddress() + " 异常");
        // 当出现异常就关闭连接
        cause.printStackTrace();
        ctx.close();
    }
}
